<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Painting</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="GUI, painting, Swing, JRuby">
<meta name="description" content="In this part of the JRuby Swing tutorial,
we do some painting.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content">


<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Painting</h1>

<p>
In this part of the JRuby Swing programming tutorial we will do some painting. 
</p>

<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 

<p>
We use painting to create charts, custom components or create games.
To do the painting, we use the painting API provided by the Swing toolkit. 
The painting is done within the <code>paintComponent</code> method. 
In the painting process, we use the <code>Graphics2D</code> object.
It is a graphics context that allows an application to draw onto components.
It is the fundamental class for rendering 2-dimensional shapes, text and images.
</p>


<h2>Colors</h2>

<p>
A color is an object representing a combination of 
Red, Green, and Blue (RGB) intensity values. We use the <code>Color</code>
class to work with colors in Swing.
</p>

<pre class="code">
#!/usr/local/bin/jruby

# ZetCode JRuby Swing tutorial
# 
# In this example we draw nine rectangles
# filled with nine different colors.
# 
# author: Jan Bodnar
# website: www.zetcode.com
# last modified: December 2010

include Java


import java.awt.Color
import javax.swing.JFrame
import javax.swing.JPanel


class Canvas &lt; JPanel

    def paintComponent g
      
        self.drawColorRectangles g
        
    end
    
    def drawColorRectangles g

        g.setColor Color.new 125, 167, 116
        g.fillRect 10, 15, 90, 60

        g.setColor Color.new 42, 179, 231
        g.fillRect 130, 15, 90, 60

        g.setColor Color.new 70, 67, 123
        g.fillRect 250, 15, 90, 60

        g.setColor Color.new 130, 100, 84
        g.fillRect 10, 105, 90, 60

        g.setColor Color.new 252, 211, 61
        g.fillRect 130, 105, 90, 60

        g.setColor Color.new 241, 98, 69
        g.fillRect 250, 105, 90, 60

        g.setColor Color.new 217, 146, 54
        g.fillRect 10, 195, 90, 60

        g.setColor Color.new 63, 121, 186
        g.fillRect 130, 195, 90, 60

        g.setColor Color.new 31, 21, 1
        g.fillRect 250, 195, 90, 60
      
    end
end    

class Example &lt; JFrame
  
    def initialize
        super "Colors"

        self.initUI
    end
      
    def initUI
        
        canvas = Canvas.new
        self.getContentPane.add canvas
        
        self.setDefaultCloseOperation JFrame::EXIT_ON_CLOSE
        self.setSize 360, 300
        self.setLocationRelativeTo nil
        self.setVisible true
    end
end

Example.new
</pre>

<p>
In the code example, we  draw nine rectangles and fill them with
different color values.
</p>

<pre class="explanation">
def paintComponent g
</pre>

<p>
Custom painting is done in <code>paintComponent</code> in most
cases. The <b>g</b> parameter is the graphics context. We call the
painting operations on this object. 
</p>

<pre class="explanation">
g.setColor Color.new 125, 167, 116
</pre>

<p>
We set the context's current color to the specified color. All subsequent 
graphics operations using this graphics context use this specified color.
</p>

<pre class="explanation">
g.fillRect 10, 15, 90, 60
</pre>

<p>
We fill a rectangle located at x=10, y=15 having width=90 and height=60 with 
the above specified color value.
</p>

<img src="/img/gui/jythonswing/colors.png" alt="Colors">
<div class="figure">Figure: Colors</div>


<h2>Shapes</h2>

<p>
The Swing painting API can draw various shapes. 
The following programming code example will show some of them. 
</p>

<pre class="code">
#!/usr/local/bin/jruby

# ZetCode JRuby Swing tutorial
# 
# This example draws simple shapes
# on a panel.
# 
# author: Jan Bodnar
# website: www.zetcode.com
# last modified: December 2010


include Java


import java.awt.Color
import java.awt.RenderingHints
import java.awt.geom.Ellipse2D
import javax.swing.JFrame
import javax.swing.JPanel


class Canvas &lt; JPanel

    def paintComponent g
        
        self.drawShapes g      
    end  
    
    def drawShapes g
      
        g.setColor Color.new 150, 150, 150

        rh = RenderingHints.new RenderingHints::KEY_ANTIALIASING,
             RenderingHints::VALUE_ANTIALIAS_ON

        rh.put RenderingHints::KEY_RENDERING,
               RenderingHints::VALUE_RENDER_QUALITY
              
        g.setRenderingHints rh

        g.fillRect 20, 20, 50, 50
        g.fillRect 120, 20, 90, 60
        g.fillRoundRect 250, 20, 70, 60, 25, 25

        g.fill Ellipse2D::Double.new 10, 100, 80, 100
        g.fillArc 120, 130, 110, 100, 5, 150
        g.fillOval 270, 130, 50, 50
      
    end
end    

class Example &lt; JFrame
  
    def initialize
        super "Shapes"

        self.initUI
    end
      
    def initUI
        
        canvas = Canvas.new
        self.getContentPane.add canvas
        
        self.setDefaultCloseOperation JFrame::EXIT_ON_CLOSE
        self.setSize 350, 250
        self.setLocationRelativeTo nil
        self.setVisible true
    end
end

Example.new
</pre>

<p>
In this code example, we draw six different shapes on the window. A
square, a rectangle, a rounded rectangle, an ellipse, an arc and
an oval. We do not draw outlines of the shapes, but we fill the
inner space of the shapes with a gray color. 
</p>

<pre class="explanation">
rh = RenderingHints.new RenderingHints::KEY_ANTIALIASING,
      RenderingHints::VALUE_ANTIALIAS_ON
</pre>

<p>
With the rendering hints, we control the quality of the painting. In
the above code, we implement antialiasing. With antialiasing, the
shapes are more smooth. 
</p>

<pre class="explanation">
g.setColor Color.new 150, 150, 150
</pre>

<p>
We will be painting in some gray color. 
</p>

<pre class="explanation">
g.fillRect 20, 20, 50, 50
g.fillRect 120, 20, 90, 60
g.fillRoundRect 250, 20, 70, 60, 25, 25
</pre>

<p>
Here we draw a rectangle, a square and a rounded rectangle. 
The first four parameters in these methods are the x, y coordinates
and width and height. The last two parameters for the <code>fillRoundRect</code>
are the horizontal and vertical diameter of the arc at the four corners. 
</p>

<pre class="explanation">
g.fill Ellipse2D::Double.new 10, 100, 80, 100
g.fillArc 120, 130, 110, 100, 5, 150
g.fillOval 270, 130, 50, 50
</pre>

<p>
These three lines draw an ellipse, an arc and an oval. 
</p>

<img src="/img/gui/jythonswing/shapes.png" alt="Shapes">
<div class="figure">Figure: Shapes</div>


<h2>Transparent rectangles</h2>

<p>
Transparency is the quality of being able to see through a material.
The easiest way to understand transparency is to imagine a piece of
glass or water. Technically, the rays of light can go through the 
glass and this way we can see objects behind the glass.
</p>

<p>
In computer graphics, we can achieve transparency effects using alpha compositing.
Alpha compositing is the process of combining an image with a background 
to create the appearance of partial transparency. 
The composition process uses an alpha channel. (wikipedia.org, answers.com) 
</p>

<pre class="code">
#!/usr/local/bin/jruby

# ZetCode JRuby Swing tutorial
# 
# This program draws ten
# rectangles with different
# levels of transparency.
# 
# author: Jan Bodnar
# website: www.zetcode.com
# last modified: December 2010


include Java

import java.awt.Color
import java.awt.AlphaComposite
import javax.swing.JFrame
import javax.swing.JPanel


class Canvas < JPanel

    def paintComponent g

        g.setColor Color::BLUE

        for i in 1..10 do
            g.setComposite AlphaComposite.getInstance AlphaComposite::SRC_OVER,
                                                        i * 0.1
            g.fillRect 50 * i, 20, 40, 40
        end
      
    end
end    

class Example &lt; JFrame
  
    def initialize
        super "Transparent rectangles"

        self.initUI
    end
      
    def initUI
        
        canvas = Canvas.new
        self.getContentPane.add canvas
        
        self.setDefaultCloseOperation JFrame::EXIT_ON_CLOSE
        self.setSize 590, 120
        self.setLocationRelativeTo nil
        self.setVisible true
    end
end

Example.new
</pre>

<p>
In the example we will draw ten rectangles with different levels of transparency. 
</p>


<pre class="explanation">
g.setComposite AlphaComposite.getInstance AlphaComposite::SRC_OVER,
                                                        i * 0.1
</pre>

<p>
The <code>AlphaComposite</code> class implements basic alpha compositing rules.
</p>

<img src="/img/gui/jythonswing/trrectangle.png" alt="Transparent rectangles">
<div class="figure">Figure: Transparent rectangles</div>


<h2>Donut Shape</h2>

<p>
In the following example we create a complex shape by rotating a bunch of ellipses. 
An affine transform is composed of zero or more linear transformations 
(rotation, scaling or shear) and translation (shift). The <code>AffineTransform</code>
is the class in Swing to perform affine transformations.
</p>

<pre class="code">
#!/usr/local/bin/jruby

# ZetCode JRuby Swing tutorial
# 
# In this code example, we create
# a Donut shape.
# 
# author: Jan Bodnar
# website: www.zetcode.com
# last modified: December 2010


include Java

import java.awt.BasicStroke
import java.awt.Color
import java.awt.RenderingHints
import java.awt.geom.AffineTransform
import java.awt.geom.Ellipse2D
import javax.swing.JFrame
import javax.swing.JPanel


class Canvas &lt; JPanel

    def paintComponent g
      
        self.drawDonut g
        
    end
    
    def drawDonut g
      
        rh = RenderingHints.new RenderingHints::KEY_ANTIALIASING,
             RenderingHints::VALUE_ANTIALIAS_ON

        rh.put RenderingHints::KEY_RENDERING,
               RenderingHints::VALUE_RENDER_QUALITY

        g.setRenderingHints rh

        size = self.getSize
        w = size.getWidth
        h = size.getHeight

        e = Ellipse2D::Double.new 0, 0, 80, 130
        g.setStroke BasicStroke.new 1
        g.setColor Color.gray

        deg = 0
        
        72.times do
            at = AffineTransform.getTranslateInstance w / 2, h / 2
            at.rotate deg/180.0 * Math::PI 
            g.draw at.createTransformedShape e
            deg += 5
        end
        
    end
end    

class Example &lt; JFrame
  
    def initialize
        super "Donut"

        self.initUI
    end
      
    def initUI
        
        canvas = Canvas.new
        self.getContentPane.add canvas
        
        self.setDefaultCloseOperation JFrame::EXIT_ON_CLOSE
        self.setSize 350, 320
        self.setLocationRelativeTo nil
        self.setVisible true
    end
end

Example.new
</pre>

<p>
In this example, we create a donut. The shape resembles a cookie, hence the name donut. 
The donut is centered in the window. 
</p>

<pre class="explanation">
size = self.getSize
w = size.getWidth
h = size.getHeight
</pre>

<p>
Here we determine the width and height of the window. We need these
values to center the donut shape. 
</p>

<pre class="explanation">
e = Ellipse2D::Double.new 0, 0, 80, 130
</pre>

<p>
We create an ellipse shape. We will rotate this ellipse to create the
donut shape. 
</p>

<pre class="explanation">
g.setStroke BasicStroke.new 1
g.setColor Color.gray
</pre>

<p>
We set the stroke and the color for the outlines of the shapes. 
</p>

<pre class="explanation">
deg = 0

72.times do
</pre>

<p>
We draw an ellipse object 72 times. Each time, we rotate the
ellipse by additional 5 degrees. This will create our donut shape.
</p>


<pre class="explanation">
at = AffineTransform.getTranslateInstance w / 2, h / 2
at.rotate deg/180.0 * Math::PI 
g.draw at.createTransformedShape e
</pre>

<p>
With the help of the <code>AffineTransform</code> class we translate
the drawing to the center of the window. Then we do rotation. 
The <code>createTransformedShape</code> method will apply these affine
transforms to the ellipse. And the transformed ellipse is drawn using
the <code>draw</code> method. The <code>rotate</code> method takes
angles in radians, so we calculate radians out of degrees.
</p>


<h2>Drawing text</h2>

<p>
In the last example, we are going to draw text
on the window. 
</p>

<pre class="code">
#!/usr/local/bin/jruby

# ZetCode JRuby Swing tutorial
# 
# In this example we draw lyrics of a 
# song on the window panel.
# 
# author: Jan Bodnar
# website: www.zetcode.com
# last modified: December 2010


include Java

import java.awt.Color
import java.awt.Font
import java.awt.RenderingHints
import java.awt.geom.Ellipse2D
import javax.swing.JFrame
import javax.swing.JPanel


class Canvas &lt; JPanel

    def paintComponent g
      
        self.drawLyrics g
    end
    
    def drawLyrics g
      
        rh = RenderingHints.new RenderingHints::KEY_ANTIALIASING,
            RenderingHints::VALUE_ANTIALIAS_ON

        rh.put RenderingHints::KEY_RENDERING,
               RenderingHints::VALUE_RENDER_QUALITY

        g.setRenderingHints rh

        g.setFont Font.new "Purisa", Font::PLAIN, 13

        g.drawString "Most relationships seem so transitory", 20, 30
        g.drawString "They're all good but not the permanent one", 20, 60
        g.drawString "Who doesn't long for someone to hold", 20, 90
        g.drawString "Who knows how to love you without being told", 20, 120
        g.drawString "Somebody tell me why I'm on my own", 20, 150
        g.drawString "If there's a soulmate for everyone", 20, 180
      
    end
end    

class Example &lt; JFrame
  
    def initialize
        super "Soulmate"

        initUI
    end
      
    def initUI
        
        canvas = Canvas.new
        self.getContentPane.add canvas
        
        self.setDefaultCloseOperation JFrame::EXIT_ON_CLOSE
        self.setSize 400, 250
        self.setLocationRelativeTo nil
        self.setVisible true
    end
end

Example.new
</pre>

<p>
We draw a lyrics of a song on the window. 
</p>

<pre class="explanation">
rh = RenderingHints.new RenderingHints::KEY_TEXT_ANTIALIASING,
    RenderingHints::VALUE_TEXT_ANTIALIAS_ON

g.setRenderingHints rh
</pre>

<p>
We apply text antialiasing on the painting. 
</p>

<pre class="explanation">
g.setFont Font.new "Purisa", Font::PLAIN, 13
</pre>

<p>
We specify the font name, style and point size, in which
we draw the lyrics.  
</p>

<pre class="explanation">
g.drawString "Most relationships seem so transitory", 20, 30
</pre>

<p>
The <code>drawString</code> method draws the text. 
</p>


<img src="/img/gui/jythonswing/soulmate.png" alt="Drawing text">
<div class="figure">Figure: Drawing text</div>


<p>
In this part of the JRuby Swing programming tutorial, we did some
painting.
</p>

<br>
<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 
<br>


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡ 
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>

<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified December 23, 2010  <span class="copyright">&copy; 2007 - 2012 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>

